<?php
namespace mz\yiiext;

use Yii;
use yii\base\InvalidConfigException;
use yii\base\InvalidRouteException;
use yii\web\Application as BaseApplication;

class Application extends BaseApplication
{
    #应用id
    private $_appid = '';
    /*
     * 应用路径
     */
    private $_appsPath;

    private $_viewPath;
    /**
     * Returns the directory that contains the view files for this module.
     * @return string the root directory of view files. Defaults to "[[basePath]]/views".
     */
    public function getViewPath()
    {

        if ($this->_viewPath === null) {

            $this->_viewPath = $this->getAppsPath() . DIRECTORY_SEPARATOR . $this->_appid . DIRECTORY_SEPARATOR . 'views';
        }
        return $this->_viewPath;
    }

    /**
     * Returns the directory that contains the view files for this module.
     * @return string the root directory of view files. Defaults to "[[basePath]]/views".
     */
    public function getAppsPath()
    {

        if ($this->_appsPath === null) {

            $this->_appsPath = Yii::getAlias('@application');
        }
        return $this->_appsPath;
    }

    /**
     * @inheritdoc
     */
    protected function bootstrap()
    {
        parent::bootstrap();
        Yii::setAlias('@application', $this->getBasePath() . DIRECTORY_SEPARATOR. "application");
    }

    public function runAction($route, $params = [])
    {

        $parts = $this->createController($route, $params);
        if (is_array($parts)) {
//            /* @var $controller string Controller */
            list($controller, $actionID) = $parts;
            $oldController = Yii::$app->controller;
            Yii::$app->controller = $controller;
            $result = $controller->runAction($actionID, $params);
            if ($oldController !== null) {
                Yii::$app->controller = $oldController;
            }

            return $result;
        } else {
            $id = $this->getUniqueId();
            throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
        }
    }
    public function getControllerNamespace()
    {
        return Yii::$app->id . '\\' . $this->_appid . '\\' . 'controllers';
    }

    public function createController($route, $params = [])
    {
        if ($route === '') {
            $route = $this->defaultRoute;
        }

        // double slashes or leading/ending slashes may cause substr problem
        $route = trim($route, '/');

        if (strpos($route, '//') !== false) {
            return false;
        }
        if (strpos($route, '/') !== false) {

            list ($id, $route) = explode('/', $route, 2);

        } else {
            $id = $route;
            $route = '';
        }
        $this->_appid = $id;
        // module and controller map take precedence
        if (isset($this->controllerMap[$id])) {
            $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
            return [$controller, $route];
        }

        $module = $this->getModule($id);
        if ($module !== null) {
            return $module->createController($route);
        }

        if (($pos = strrpos($route, '/')) !== false) {
            $id = substr($route, 0, $pos);
            $route = substr($route, $pos + 1);
        }
        $controller = $this->createControllerByID($id);
        if ($controller === null && $route !== '') {
            $controller = $this->createControllerByID($id . '/' . $route);
            $route = '';
        }

        return $controller === null ? false : [$controller, $route];
    }
    public function createControllerByID($id)
    {
        $pos = strrpos($id, '/');
        if ($pos === false) {
            $prefix = '';
            $className = $id;
        } else {
            $prefix = substr($id, 0, $pos+1);
            $className = substr($id, $pos + 1);
        }

        /*echo 'id=' .$id."\r\n";
        echo 'prefix=' .$prefix."\r\n";
        echo 'className=' .$className."\r\n";
        echo $this->getControllerNamespace()."\r\n";*/
        //exit;
        if (!preg_match('%^[a-z][a-z0-9\\-_]*$%', $className)) {
            return null;
        }
        if ($prefix !== '' && !preg_match('%^[a-z0-9_/]+$%i', $prefix)) {
            return null;
        }

        $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller';


        //$className = '\\'.ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix)  . $className, '\\');
        $className = ltrim($this->getControllerNamespace() . '\\' . str_replace('/', '\\', $prefix)  . $className, '\\');
        /*echo $className;
        exit;*/
        if (strpos($className, '-') !== false || !class_exists($className)) {
            return null;
        }

        if (is_subclass_of($className, 'yii\base\Controller')) {
            $controller = Yii::createObject($className, [$id, $this]);
            return get_class($controller) === $className ? $controller : null;
        } elseif (YII_DEBUG) {
            throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
        }
        return null;
    }
}